#include <gflags/gflags.h>
#include <gtest/gtest.h>

#include "logger.hpp"
#include "channel.hpp"
#include "etcd.hpp"
#include "utils.hpp"

#include "base.pb.h"
#include "friend.pb.h"
#include "message.pb.h"
#include "user.pb.h"

DEFINE_bool(run_mode, true, "是否为调试模式");
DEFINE_string(log_file, "", "发布模式下，用于指定日志的输出文件");
DEFINE_int32(log_level, 0, "发布模式下，用于指定日志输出等级");

DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(friend_service, "/service/friend_service", "服务监控根目录");

class FriendClientTest: public testing::Test{
    protected:
    void SetUp() override{
        // 绑定 RPC 信道
        auto sm = std::make_shared<im::ServiceManager>();
        sm->declared(FLAGS_friend_service);
        auto put_cb = std::bind(&im::ServiceManager::onServiceOnline, sm.get(), std::placeholders::_1, std::placeholders::_2);
        auto del_cb = std::bind(&im::ServiceManager::onServiceOffline, sm.get(), std::placeholders::_1, std::placeholders::_2);
        // 初始化服务发现
        im::Discover::ptr dclient = std::make_shared<im::Discover>(FLAGS_etcd_host, FLAGS_base_service, put_cb, del_cb);
        channel = sm->choose(FLAGS_friend_service);
        if (!channel) {
            im::LOG_CRITICAL("Failed to get RPC channel");
        }

        buildTestData();
    }

    void buildTestData(){
        // 构建测试数据
        std::vector<std::string> user_names{"爸爸", "妈妈", "小张", "小兰"};
        std::vector<std::string> user_phones{"11111111111", "12222222222", "13333333333", "14444444444"};
        std::vector<std::string> user_descriptions{"父亲", "母亲", "儿子", "女儿"};
        std::vector<std::string> user_avatars{"爸爸的头像", "妈妈的头像", "小张的头像", "小兰的头像"};

        for(int i = 0; i < 4; i++){
            im::UserInfo user;
            user.set_user_id(std::to_string(i+1));
            user.set_nickname(user_names[i]);
            user.set_phone(user_phones[i]);
            user.set_description(user_descriptions[i]);
            user.set_avatar(user_avatars[i]);
            users_list.push_back(user);
        }
    }
    
    void TearDown() override{
        // 清理资源
    }

    im::ServiceChannel::ChannelPtr channel;
    std::string login_ssid;
    std::vector<im::UserInfo> users_list;   // 四个人：爸，妈，小张，小兰
};

/// @brief 爸爸，小张，小兰都申请妈妈为好友 
TEST_F(FriendClientTest, FriendAdd){
    im::FriendService_Stub stub(channel.get());
    for(int i = 0; i < 4; i++){
        if(i == 1) 
            continue;
        printf("-----申请人ID：%s-----\n", users_list[i].user_id().c_str());
        im::FriendAddReq req;
        std::string rid = im::uuid();
        req.set_request_id(rid);
        req.set_user_id(users_list[i].user_id());
        req.set_respondent_id(users_list[1].user_id());
        im::FriendAddRsp rsp;
        brpc::Controller cntl;
        stub.FriendAdd(&cntl, &req, &rsp, nullptr);
        ASSERT_FALSE(cntl.Failed());
        EXPECT_EQ(rsp.request_id(), rid);
        EXPECT_TRUE(rsp.success());
        EXPECT_EQ(rsp.errmsg(), "");
    }
}

/// @brief 妈妈查看所有好友申请列表
TEST_F(FriendClientTest, GetPendingFriendEventList){
    im::FriendService_Stub stub(channel.get());
    im::GetPendingFriendEventListReq req;
    std::string rid = im::uuid();
    req.set_request_id(rid);
    req.set_user_id("2");
    im::GetPendingFriendEventListRsp rsp;
    brpc::Controller cntl;
    stub.GetPendingFriendEventList(&cntl, &req, &rsp, nullptr);

    ASSERT_FALSE(cntl.Failed());
    EXPECT_EQ(rsp.request_id(), rid);
    EXPECT_TRUE(rsp.success());
    EXPECT_EQ(rsp.event_size(), 3);
    for(int i = 0; i < rsp.event_size(); i++){
        std::cout << "---------------" << std::endl;
        std::cout << rsp.event(i).sender().user_id() << std::endl;
        std::cout << rsp.event(i).sender().nickname() << std::endl;
        std::cout << rsp.event(i).sender().phone() << std::endl;
        std::cout << rsp.event(i).sender().description() << std::endl;
        std::cout << rsp.event(i).sender().avatar() << std::endl;
    }
}

/// @brief 妈妈同意爸爸、小兰的好友申请，拒绝小张的好友申请
TEST_F(FriendClientTest, FriendAddProcess){
    im::FriendService_Stub stub(channel.get());
    for(int i = 0; i < 4; i++){
        if(i == 1) continue;
        im::FriendAddProcessReq req;
        im::FriendAddProcessRsp rsp;
        brpc::Controller cntl;
        bool argee;
        if(i == 0 || i == 3){   // 爸爸、小兰
            argee = true;
            req.set_apply_user_id(users_list[i].user_id());
        }else{  // 小张
            argee = false;
            req.set_apply_user_id(users_list[i].user_id());
        }
        req.set_request_id(im::uuid());
        req.set_agree(argee);
        req.set_user_id(users_list[1].user_id());

        stub.FriendAddProcess(&cntl, &req, &rsp, nullptr);
        ASSERT_FALSE(cntl.Failed());
        EXPECT_TRUE(rsp.success());
        EXPECT_EQ(rsp.errmsg(), "");
        if(i == 0 || i == 3)
            std::cout << "新单聊会话的ID:" << rsp.new_session_id() << std::endl;
    }
}

/// @brief 进行用户搜索，可以搜索到小张
TEST_F(FriendClientTest, FriendSearch){
    im::FriendService_Stub stub(channel.get());
    im::FriendSearchReq req;
    im::FriendSearchRsp rsp;
    req.set_request_id(im::uuid());
    req.set_user_id(users_list[1].user_id());
    req.set_search_key("小");
    brpc::Controller cntl;
    stub.FriendSearch(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    EXPECT_TRUE(rsp.success());
    for (int i = 0; i < rsp.user_info_size(); i++) {
        std::cout << "-------------------\n";
        std::cout << rsp.user_info(i).user_id() << std::endl;
        std::cout << rsp.user_info(i).nickname() << std::endl;
        std::cout << rsp.user_info(i).avatar() << std::endl;
    }
}

/// @brief 妈妈查看所有好友列表
TEST_F(FriendClientTest, GetFriendList){
    im::FriendService_Stub stub(channel.get());
    im::GetFriendListReq req;
    std::string rid = im::uuid();
    req.set_request_id(rid);
    req.set_user_id("2");
    im::GetFriendListRsp rsp;
    brpc::Controller cntl;
    stub.GetFriendList(&cntl, &req, &rsp, nullptr);

    ASSERT_FALSE(cntl.Failed());
    EXPECT_EQ(rsp.request_id(), rid);
    EXPECT_TRUE(rsp.success());
    EXPECT_EQ(rsp.friend_list_size(), 2);
    for(int i = 0; i < rsp.friend_list_size(); i++){
        std::cout << "---------------" << std::endl;
        std::cout << rsp.friend_list(i).user_id() << std::endl;
        std::cout << rsp.friend_list(i).nickname() << std::endl;
        std::cout << rsp.friend_list(i).phone() << std::endl;
        std::cout << rsp.friend_list(i).description() << std::endl;
        std::cout << rsp.friend_list(i).avatar() << std::endl;
    }
}

/// @brief 妈妈删除好友小兰
TEST_F(FriendClientTest, FriendRemove){
    im::FriendService_Stub stub(channel.get());
    im::FriendRemoveReq req;
    im::FriendRemoveRsp rsp;
    req.set_request_id(im::uuid());
    req.set_user_id(users_list[1].user_id());   // 妈妈
    req.set_peer_id(users_list[3].user_id());   // 小兰
    brpc::Controller cntl;
    stub.FriendRemove(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    EXPECT_TRUE(rsp.success());
    EXPECT_EQ(rsp.errmsg(), "");
}

/// @brief 爸爸发起群聊，拉上妈妈，小张，小兰
TEST_F(FriendClientTest, ChatSessionCreate){
    im::FriendService_Stub stub(channel.get());
    im::ChatSessionCreateReq req;
    im::ChatSessionCreateRsp rsp;
    req.set_request_id(im::uuid());
    req.set_user_id(users_list[0].user_id());   // 爸爸
    req.set_chat_session_name("快乐一家人");
    for (auto &user : users_list) {
        req.add_member_id_list(user.user_id());
    }
    brpc::Controller cntl;
    stub.ChatSessionCreate(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    EXPECT_TRUE(rsp.success());
    EXPECT_EQ(rsp.errmsg(), "");
    std::cout << rsp.chat_session_info().chat_session_id() << std::endl;
    std::cout << rsp.chat_session_info().chat_session_name() << std::endl;
}

/// @brief 爸爸发送一条群聊信息，获取会话列表，并查看群聊信息
TEST_F(FriendClientTest, GetChatSessionList){
    im::FriendService_Stub stub(channel.get());
    im::GetChatSessionListReq req;
    im::GetChatSessionListRsp rsp;
    req.set_request_id(im::uuid());
    req.set_user_id(users_list[0].user_id());   // 爸爸
    brpc::Controller cntl;
    std::cout << "发送获取聊天会话列表请求！！\n";
    stub.GetChatSessionList(&cntl, &req, &rsp, nullptr);
    std::cout << "请求发送完毕！！\n";
    ASSERT_FALSE(cntl.Failed());
    EXPECT_TRUE(rsp.success());
    EXPECT_EQ(rsp.errmsg(), "");
    std::cout << "请求发送完毕，且成功！！\n";
    for (int i = 0; i < rsp.chat_session_info_list_size(); i++) {
        std::cout << "-------------------\n";
        std::cout << rsp.chat_session_info_list(i).single_chat_friend_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).chat_session_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).chat_session_name() << std::endl;
        std::cout << rsp.chat_session_info_list(i).avatar() << std::endl;
        std::cout << "消息内容：\n";
        std::cout << rsp.chat_session_info_list(i).prev_message().message_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().chat_session_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().timestamp() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().sender().user_id() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().sender().nickname() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().sender().avatar() << std::endl;
        std::cout << rsp.chat_session_info_list(i).prev_message().message().speech_message().file_contents() << std::endl;
    }
}

/// @brief 小张查看群聊成员
TEST_F(FriendClientTest, GetChatSessionMember){
    im::FriendService_Stub stub(channel.get());
    im::GetChatSessionMemberReq req;
    im::GetChatSessionMemberRsp rsp;
    req.set_request_id(im::uuid());
    req.set_user_id(users_list[2].user_id());   // 小张
    req.set_chat_session_id("d431-46eee757-0002");  // 爸爸创建的群聊
    brpc::Controller cntl;
    stub.GetChatSessionMember(&cntl, &req, &rsp, nullptr);
    ASSERT_FALSE(cntl.Failed());
    EXPECT_TRUE(rsp.success());
    EXPECT_EQ(rsp.errmsg(), "");
    for (int i = 0; i < rsp.member_info_list_size(); i++) {
        std::cout << "-------------------\n";
        std::cout << rsp.member_info_list(i).user_id() << std::endl;
        std::cout << rsp.member_info_list(i).nickname() << std::endl;
        std::cout << rsp.member_info_list(i).avatar() << std::endl;
    }
}

int main(int argc, char *argv[]) {
    testing::InitGoogleTest(&argc, argv);
    google::ParseCommandLineFlags(&argc, &argv, true);
    im::initLogger(FLAGS_run_mode, FLAGS_log_file, FLAGS_log_level);

    return RUN_ALL_TESTS();
}